#!/bin/bash

# 设置严格模式
set -euo pipefail

# 日志文件配置
LOG_DIR="/home/ap/appoper/logs"
LOG_FILE="$LOG_DIR/sftp_upload_$(date +'%Y%m%d_%H%M%S').log"

# 创建日志目录
mkdir -p "$LOG_DIR"

# 记录日志函数
log() {
    local level="$1"
    shift
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] [$level] $*" | tee -a "$LOG_FILE"
}

# 获取上个月的年月(格式: YYYYMM)
LAST_MONTH=$(date -d "last month" +"%Y%m")

log "INFO" "开始执行SFTP上传脚本"
log "INFO" "上个月日期: $LAST_MONTH"

# 本地和远程路径配置
LOCAL_BASE="/home/ap/appoper"
REMOTE_BASE="/home/ap/appoper"
A_DATA_DIR="A数据"

# SFTP连接信息
SFTP_SERVER="10.34.2.32"
SFTP_PORT="10022"
SFTP_USER="appoper"
SFTP_PASS="bb@123"

# 本地完整路径
LOCAL_DIR="$LOCAL_BASE/$LAST_MONTH/$A_DATA_DIR"

# 检查本地目录是否存在
if [ ! -d "$LOCAL_DIR" ]; then
    log "ERROR" "本地目录不存在: $LOCAL_DIR"
    exit 1
fi

log "INFO" "本地目录: $LOCAL_DIR"
log "INFO" "远程目录: $REMOTE_BASE/$LAST_MONTH/$A_DATA_DIR"

# 使用expect处理交互式SFTP并记录日志
log "INFO" "开始SFTP传输过程"
/usr/bin/expect <<'EOF' | tee -a "$LOG_FILE"
set timeout 30
spawn sftp -oPort=$SFTP_PORT $SFTP_USER@$SFTP_SERVER
expect {
    "password:" {
        send "$SFTP_PASS\r"
    }
    timeout {
        puts "连接超时"
        exit 1
    }
    eof {
        puts "连接失败"
        exit 1
    }
}
expect "sftp>"

# 进入远程目录并创建数据目录
send "cd $REMOTE_BASE/$LAST_MONTH\r"
expect "sftp>"
send "mkdir -p \"$A_DATA_DIR\"\r"
expect "sftp>"
send "cd \"$A_DATA_DIR\"\r"
expect "sftp>"

# 处理文件列表
set failed_files 0
set success_files 0

# 切换到本地目录
send "lcd \"$LOCAL_DIR\"\r"
expect "sftp>"

# 获取本地文件列表
set temp_file "/tmp/sftp_upload_list_[pid].txt"
send "!ls \"$LOCAL_DIR\" > $temp_file\r"
expect "sftp>"
send "!cat $temp_file\r"
expect {
    -re {([^\r\n]*)\r\n} {
        set files [split $expect_out(1,string) "\n"]
    }
    timeout {
        puts "获取本地文件列表超时"
        exit 1
    }
}
send "!rm -f $temp_file\r"
expect "sftp>"

# 上传文件
foreach file $files {
    if {$file eq ""} continue
    
    puts "正在上传文件: $file"
    
    # 上传重试机制
    set retry 3
    while {$retry > 0} {
        send "put \"$file\"\r"
        expect {
            "100%" {
                incr success_files
                puts "文件上传成功: $file"
                break
            }
            "sftp>" {
                # 上传完成，检查是否成功
                send "ls -l \"$file\"\r"
                expect {
                    -re {[-rwx]+\s+\d+\s+\d+\s+\d+\s+\d+} {
                        incr success_files
                        puts "文件上传成功: $file"
                        break
                    }
                    timeout {
                        incr retry -1
                        if {$retry == 0} {
                            incr failed_files
                            puts "文件 $file 上传失败 (验证超时)"
                        }
                    }
                }
                break
            }
            timeout {
                incr retry -1
                if {$retry == 0} {
                    incr failed_files
                    puts "文件 $file 上传失败 (重试次数用尽)"
                } else {
                    puts "文件 $file 上传超时，剩余重试次数: $retry"
                }
            }
        }
    }
}

# 保存结果到环境变量
set ::env(UPLOAD_SUCCESS_COUNT) $success_files
set ::env(UPLOAD_FAILED_COUNT) $failed_files

send "exit\r"
expect eof
EOF

# 获取expect脚本的返回状态和上传结果
EXPECT_STATUS=$?
SUCCESS_COUNT=${UPLOAD_SUCCESS_COUNT:-0}
FAILED_COUNT=${UPLOAD_FAILED_COUNT:-0}

# 检查执行结果
if [ $EXPECT_STATUS -eq 0 ] && [ "$FAILED_COUNT" -eq 0 ]; then
    log "INFO" "所有文件($SUCCESS_COUNT个)上传成功到 $SFTP_SERVER:$REMOTE_BASE/$LAST_MONTH/$A_DATA_DIR"
    echo "所有文件上传成功，详情请查看日志: $LOG_FILE"
    exit 0
else
    log "ERROR" "文件上传完成，成功${SUCCESS_COUNT}个，失败${FAILED_COUNT}个"
    echo "文件上传完成，有${FAILED_COUNT}个文件失败，详情请查看日志: $LOG_FILE"
    exit 1
fi
